package edu.rpi.tw.provenance.pc3.emulators;

import java.util.*;

import edu.rpi.tw.provenance.pc3.util.*;
import edu.rpi.tw.provenance.protoprov.*;

public class LoadWorkflow {

	public ProtoProv RunPANSTAARS(String pJobID, String pCSVRootPath) throws Exception {
		ProtoProv protoprov = new ProtoProv();
		IdGenerator idGen = new IdGenerator();
		
		String scope = "main";
		
		// ANNOTATION //
		String provGroup = "ALL";
		protoprov.AddGroup(provGroup);
		List<String> provGroups = new ArrayList<String>();
		provGroups.add(provGroup);
		// END //

		// ANNOTATION //
		String provCtlUsr = "USER";
		protoprov.AddController(provCtlUsr, provGroups);
		String provCtlSys = "SYSTEM";
		protoprov.AddController(provCtlSys, provGroups);
		// END //
		String JobID = pJobID, CSVRootPath = pCSVRootPath;

		// ANNOTATION //
		String provVarJobID = idGen.newVariableId(scope, "String", "JobId");
		protoprov.AddVariable(provVarJobID, JobID, provGroups);
		String provVarCSVRootPath = idGen.newVariableId(scope, "String", "CSVRootPath");
		protoprov.AddVariable(provVarCSVRootPath, CSVRootPath, provGroups);
		String provFxnDirectAssertion = idGen.newFunctionId(scope, "DirectAssertion");
		protoprov.AddFunction(provFxnDirectAssertion, "DirectAssertion", provGroups);

		
		protoprov.AddWGB(idGen.newRelationId("WGB"), provVarJobID, "generated by", provFxnDirectAssertion, provGroups);
		protoprov.AddWGB(idGen.newRelationId("WGB"), provVarCSVRootPath, "generated by", provFxnDirectAssertion, provGroups);
		protoprov.AddWCB(idGen.newRelationId("WCB"), provFxnDirectAssertion, "controlled by", provCtlUsr, provGroups);
		// END //

		// ///////////////////////////////////
		// //// Batch Initialization //////
		// ///////////////////////////////////
		// 1. IsCSVReadyFileExists
		boolean IsCSVReadyFileExistsOutput = LoadAppLogic.IsCSVReadyFileExists(CSVRootPath);
		// ANNOTATION //
		String provVarIsCSVReadyFileExistsOutput = idGen.newVariableId(scope, "boolean", "IsCSVReadyFileExistsOutput");
		protoprov.AddVariable(provVarIsCSVReadyFileExistsOutput, IsCSVReadyFileExistsOutput, provGroups);

		String provFxnIsCSVReadyFileExists = idGen.newFunctionId(scope, "IsCSVReadyFileExists");
		protoprov.AddFunction(provFxnIsCSVReadyFileExists, "IsCSVReadyFileExists", provGroups);
		protoprov.AddUsed(idGen.newRelationId("USD"), provFxnIsCSVReadyFileExists, "file path", provVarCSVRootPath, provGroups);
		protoprov.AddWGB(idGen.newRelationId("WGB"), provVarIsCSVReadyFileExistsOutput, "output", provFxnIsCSVReadyFileExists, provGroups);
		protoprov.AddWCB(idGen.newRelationId("WCB"), provFxnIsCSVReadyFileExists, "controlled by", provCtlSys, provGroups);
		// END //
		
		// 2. Control Flow: Decision

		// ANNOTATION //
		String provFxnCheck_IsCSVReadyFileExists = idGen.newFunctionId(scope, "Check_IsCSVReadyFileExists");
		protoprov.AddFunction(provFxnCheck_IsCSVReadyFileExists, "Check_IsCSVReadyFileExists", provGroups);
		protoprov.AddUsed(idGen.newRelationId("USD"), provFxnCheck_IsCSVReadyFileExists, "control flow checkpoint", provVarIsCSVReadyFileExistsOutput, provGroups);
		// END//
		
		if (!IsCSVReadyFileExistsOutput) {
			String provFxnEndState = idGen.newFunctionId(scope, "EndState");
			protoprov.AddFunction(provFxnEndState, "EndState", provGroups);
			protoprov.AddWTB(idGen.newRelationId("WTB"), provFxnEndState, "failed control flow check", provFxnCheck_IsCSVReadyFileExists, provGroups);			
			String provVarEndValue = idGen.newFunctionId(scope, "EndValue");
			protoprov.AddVariable(provVarEndValue, "false", provGroups);
			protoprov.AddWGB(idGen.newRelationId("WGB"), provVarEndValue, "end state value", provFxnEndState, provGroups);
			return protoprov;
		}
		
		// 3. ReadCSVReadyFile
		List<LoadAppLogic.CSVFileEntry> ReadCSVReadyFileOutput =
			LoadAppLogic.ReadCSVReadyFile(CSVRootPath);

		// ANNOTATION //
		String provVarReadCSVReadyFileOutput = idGen.newVariableId(scope, "List<CSVFileEntry>", "ReadCSVReadyFileOutput");
		protoprov.AddVariable(provVarReadCSVReadyFileOutput, "ReadCSVReadyFileOutput", provGroups);
		String provFxnReadCSVReadyFile = idGen.newFunctionId(scope, "ReadCSVReadyFile");
		protoprov.AddFunction(provFxnReadCSVReadyFile, "ReadCSVReadyFile", provGroups);
		protoprov.AddUsed(idGen.newRelationId("USD"), provFxnReadCSVReadyFile, "file path", provVarCSVRootPath, provGroups);
		//protoprov.AddUsed(idGen.newRelationId("USD"), provFxnReadCSVReadyFile, "check IsCSVReadyFileExistsOutput", provVarIsCSVReadyFileExistsOutput, provGroups);
		protoprov.AddWGB(idGen.newRelationId("WGB"), provVarReadCSVReadyFileOutput, "output", provFxnReadCSVReadyFile, provGroups);
		protoprov.AddWCB(idGen.newRelationId("WCB"), provFxnReadCSVReadyFile, "controlled by", provCtlSys, provGroups);
		protoprov.AddWTB(idGen.newRelationId("WTB"), provFxnReadCSVReadyFile, "passed control flow check", provFxnCheck_IsCSVReadyFileExists, provGroups);			
		// END //		
		
		// 4. IsMatchCSVFileTables
		boolean IsMatchCSVFileTablesOutput = LoadAppLogic.IsMatchCSVFileTables(ReadCSVReadyFileOutput);

		// ANNOTATION //
		String provVarIsMatchCSVFileTablesOutput = idGen.newVariableId(scope, "boolean", "IsMatchCSVFileTablesOutput");
		protoprov.AddVariable(provVarIsMatchCSVFileTablesOutput, IsMatchCSVFileTablesOutput, provGroups);
		String provFxnIsMatchCSVFileTables = idGen.newFunctionId(scope, "IsMatchCSVFileTables");	
		protoprov.AddFunction(provFxnIsMatchCSVFileTables, "IsMatchCSVFileTables", provGroups);
		protoprov.AddUsed(idGen.newRelationId("USD"), provFxnIsMatchCSVFileTables, "file list", provVarReadCSVReadyFileOutput, provGroups);
		protoprov.AddWGB(idGen.newRelationId("WGB"), provVarIsMatchCSVFileTablesOutput, "output", provFxnIsMatchCSVFileTables, provGroups);
		protoprov.AddWCB(idGen.newRelationId("WCB"), provFxnIsMatchCSVFileTables, "controlled by", provCtlSys, provGroups);
		// END //		
				
		// 5. Control Flow: Decision
		
		// ANNOTATION //
		String provFxnCheck_IsMatchCSVFileTables = idGen.newFunctionId(scope, "Check_IsMatchCSVFileTables");
		protoprov.AddFunction(provFxnCheck_IsMatchCSVFileTables, "Check_IsMatchCSVFileTables", provGroups);
		protoprov.AddUsed(idGen.newRelationId("USD"), provFxnCheck_IsMatchCSVFileTables, "control flow checkpoint", provVarIsMatchCSVFileTablesOutput, provGroups);
		// END//
		
		if (!IsMatchCSVFileTablesOutput) {
			String provFxnEndState = idGen.newFunctionId(scope, "EndState");
			protoprov.AddFunction(provFxnEndState, "EndState", provGroups);
			protoprov.AddWTB(idGen.newRelationId("WTB"), provFxnEndState, "failed control flow check", provFxnCheck_IsMatchCSVFileTables, provGroups);			
			String provVarEndValue = idGen.newFunctionId(scope, "EndValue");
			protoprov.AddVariable(provVarEndValue, "false", provGroups);
			protoprov.AddWGB(idGen.newRelationId("WGB"), provVarEndValue, "end state value", provFxnEndState, provGroups);
			return protoprov;
		}

		// 6. CreateEmptyLoadDB
		LoadAppLogic.DatabaseEntry CreateEmptyLoadDBOutput = LoadAppLogic.CreateEmptyLoadDB(JobID);

		// ANNOTATION //
		String provVarCreateEmptyLoadDBOutput = idGen.newVariableId(scope, "DatabaseEntry", "CreateEmptyLoadDBOutput");
		protoprov.AddVariable(provVarCreateEmptyLoadDBOutput, CreateEmptyLoadDBOutput, provGroups);
		String provFxnCreateEmptyLoadDB = idGen.newFunctionId(scope, "CreateEmptyLoadDB");
		protoprov.AddFunction(provFxnCreateEmptyLoadDB, "CreateEmptyLoadDB", provGroups);
		
		protoprov.AddUsed(idGen.newRelationId("USD"), provFxnCreateEmptyLoadDB, "Job ID", provVarJobID, provGroups);
		//protoprov.AddUsed(idGen.newRelationId("USD"), provFxnCreateEmptyLoadDB, "check IsMatchCSVFileTablesOutput", provVarIsMatchCSVFileTablesOutput, provGroups);
		protoprov.AddWGB(idGen.newRelationId("WGB"), provVarCreateEmptyLoadDBOutput, "output", provFxnCreateEmptyLoadDB, provGroups);
		protoprov.AddWCB(idGen.newRelationId("WCB"), provFxnCreateEmptyLoadDB, "controlled by", provCtlSys, provGroups);
		protoprov.AddWTB(idGen.newRelationId("WTB"), provFxnCreateEmptyLoadDB, "passed control flow check", provFxnCheck_IsMatchCSVFileTables, provGroups);			

		// END //				
		
		int counter = 1;
		String lastCheck = "";
		String provVarDbEntryP2Detection = "";
		String provVarDbEntryP2ImageMeta = "";
		// 7. Control Flow: Loop. ForEach CSVFileEntry in ReadCSVReadyFileOutput
		// Do...
		for (LoadAppLogic.CSVFileEntry FileEntry : ReadCSVReadyFileOutput) {
			scope = "ForIter" + counter;

			// ANNOTATION //
			String provVarFileEntry = idGen.newVariableId(scope, "CSVFileEntry", "FileEntry");
			protoprov.AddVariable(provVarFileEntry, FileEntry.FilePath + "-" + FileEntry.TargetTable, provGroups);
			String provFxnForEach = idGen.newFunctionId(scope, "ForEach");
			protoprov.AddFunction(provFxnForEach, "ForEach", provGroups);
			protoprov.AddUsed(idGen.newRelationId("USD"), provFxnForEach, "file list", provVarReadCSVReadyFileOutput, provGroups);
			if(counter > 1)
				protoprov.AddUsed(idGen.newRelationId("USD"), provFxnForEach, "IsMatchTableColumnRangesOutput check", lastCheck, provGroups);
			protoprov.AddWGB(idGen.newRelationId("WGB"), provVarFileEntry, "output", provFxnForEach, provGroups);			
			protoprov.AddWCB(idGen.newRelationId("WCB"), provFxnForEach, "controlled by", provCtlSys, provGroups);
			// END //				
			
			// ///////////////////////////////////
			// //// Pre Load Validation //////
			// ///////////////////////////////////
			// 7.a. IsExistsCSVFile
			boolean IsExistsCSVFileOutput = LoadAppLogic.IsExistsCSVFile(FileEntry);
			// ANNOTATION //
			String provVarIsExistsCSVFileOutput = idGen.newVariableId(scope, "boolean", "IsExistsCSVFileOutput");
			protoprov.AddVariable(provVarIsExistsCSVFileOutput, IsExistsCSVFileOutput, provGroups);
			String provFxnIsExistsCSVFile = idGen.newFunctionId(scope, "IsExistsCSVFile");
			protoprov.AddFunction(provFxnIsExistsCSVFile, "IsExistsCSVFile", provGroups);
			protoprov.AddUsed(idGen.newRelationId("USD"), provFxnIsExistsCSVFile, "file entry", provVarFileEntry, provGroups);
			protoprov.AddWGB(idGen.newRelationId("WGB"), provVarIsExistsCSVFileOutput, "output", provFxnIsExistsCSVFile, provGroups);
			protoprov.AddWCB(idGen.newRelationId("WCB"), provFxnIsExistsCSVFile, "controlled by", provCtlSys, provGroups);
			// END //		
			
			// 7.b. Control Flow: Decision
			
			// ANNOTATION //
			String provFxnCheck_IsExistsCSVFile = idGen.newFunctionId(scope, "Check_IsExistsCSVFile");
			protoprov.AddFunction(provFxnCheck_IsExistsCSVFile, "Check_IsExistsCSVFile", provGroups);
			protoprov.AddUsed(idGen.newRelationId("USD"), provFxnCheck_IsExistsCSVFile, "control flow checkpoint", provVarIsExistsCSVFileOutput, provGroups);
			// END//
			
			if (!IsExistsCSVFileOutput) {
				String provFxnEndState = idGen.newFunctionId(scope, "EndState");
				protoprov.AddFunction(provFxnEndState, "EndState", provGroups);
				protoprov.AddWTB(idGen.newRelationId("WTB"), provFxnEndState, "failed control flow check", provFxnCheck_IsExistsCSVFile, provGroups);			
				String provVarEndValue = idGen.newFunctionId(scope, "EndValue");
				protoprov.AddVariable(provVarEndValue, "false", provGroups);
				protoprov.AddWGB(idGen.newRelationId("WGB"), provVarEndValue, "end state value", provFxnEndState, provGroups);
				return protoprov;
			}

			// 7.c. ReadCSVFileColumnNames
			LoadAppLogic.CSVFileEntry ReadCSVFileColumnNamesOutput =
				LoadAppLogic.ReadCSVFileColumnNames(FileEntry);


			// ANNOTATION //
			String provVarReadCSVFileColumnNamesOutput = idGen.newVariableId(scope, "CSVFileEntry", "ReadCSVFileColumnNamesOutput");
			protoprov.AddVariable(provVarReadCSVFileColumnNamesOutput, FileEntry.FilePath + "-" + FileEntry.TargetTable, provGroups);
			String provFxnReadCSVFileColumnNames = idGen.newFunctionId(scope, "ReadCSVFileColumnNames");
			protoprov.AddFunction(provFxnReadCSVFileColumnNames, "ReadCSVFileColumnNames", provGroups);
			//protoprov.AddUsed(idGen.newRelationId("USD"), provFxnReadCSVFileColumnNames, "check IsExistsCSVFileOutput", provVarIsExistsCSVFileOutput, provGroups);
			protoprov.AddUsed(idGen.newRelationId("USD"), provFxnReadCSVFileColumnNames, "file entry", provVarFileEntry, provGroups);
			protoprov.AddWGB(idGen.newRelationId("WGB"), provVarReadCSVFileColumnNamesOutput, "output", provFxnReadCSVFileColumnNames, provGroups);
			protoprov.AddWCB(idGen.newRelationId("WCB"), provFxnReadCSVFileColumnNames, "controlled by", provCtlSys, provGroups);
			protoprov.AddWTB(idGen.newRelationId("WTB"), provFxnReadCSVFileColumnNames, "passed control flow check", provFxnCheck_IsExistsCSVFile, provGroups);			
			// END //				

			// 7.d. IsMatchCSVFileColumnNames
			boolean IsMatchCSVFileColumnNamesOutput =
				LoadAppLogic.IsMatchCSVFileColumnNames(ReadCSVFileColumnNamesOutput);

			// ANNOTATION //
			String provVarIsMatchCSVFileColumnNamesOutput = idGen.newVariableId(scope, "boolean", "IsMatchCSVFileColumnNamesOutput");
			protoprov.AddVariable(provVarIsMatchCSVFileColumnNamesOutput, IsMatchCSVFileColumnNamesOutput, provGroups);
			String provFxnIsMatchCSVFileColumnNames = idGen.newFunctionId(scope, "IsMatchCSVFileColumnNames");
			protoprov.AddFunction(provFxnIsMatchCSVFileColumnNames, "IsMatchCSVFileColumnNames", provGroups);
			protoprov.AddUsed(idGen.newRelationId("USD"), provFxnIsMatchCSVFileColumnNames, "file entry", provVarReadCSVFileColumnNamesOutput, provGroups);
			protoprov.AddWGB(idGen.newRelationId("WGB"), provVarIsMatchCSVFileColumnNamesOutput, "output", provFxnIsMatchCSVFileColumnNames, provGroups);
			protoprov.AddWCB(idGen.newRelationId("WCB"), provFxnIsMatchCSVFileColumnNames, "controlled by", provCtlSys, provGroups);
			// END //				
			
			// 7.e. Control Flow: Decision
			
			// ANNOTATION //
			String provFxnCheck_IsMatchCSVFileColumnNames = idGen.newFunctionId(scope, "Check_IsMatchCSVFileColumnNames");
			protoprov.AddFunction(provFxnCheck_IsMatchCSVFileColumnNames, "Check_IsMatchCSVFileColumnNames", provGroups);
			protoprov.AddUsed(idGen.newRelationId("USD"), provFxnCheck_IsMatchCSVFileColumnNames, "control flow checkpoint", provVarIsMatchCSVFileColumnNamesOutput, provGroups);
			// END//
			
			if (!IsMatchCSVFileColumnNamesOutput) {
				String provFxnEndState = idGen.newFunctionId(scope, "EndState");
				protoprov.AddFunction(provFxnEndState, "EndState", provGroups);
				protoprov.AddWTB(idGen.newRelationId("WTB"), provFxnEndState, "failed control flow check", provFxnCheck_IsMatchCSVFileColumnNames, provGroups);			
				String provVarEndValue = idGen.newFunctionId(scope, "EndValue");
				protoprov.AddVariable(provVarEndValue, "false", provGroups);
				protoprov.AddWGB(idGen.newRelationId("WGB"), provVarEndValue, "end state value", provFxnEndState, provGroups);
				return protoprov;
			}


			// ///////////////////////////////////
			// //// Load File //////
			// ///////////////////////////////////
			// 7.f. LoadCSVFileIntoTable
			boolean LoadCSVFileIntoTableOutput =
				LoadAppLogic.LoadCSVFileIntoTable(CreateEmptyLoadDBOutput, ReadCSVFileColumnNamesOutput);
			
			// ANNOTATION //
			String provVarLoadCSVFileIntoTableOutput = idGen.newVariableId(scope, "boolean", "LoadCSVFileIntoTableOutput");
			protoprov.AddVariable(provVarLoadCSVFileIntoTableOutput, LoadCSVFileIntoTableOutput, provGroups);
			String provFxnLoadCSVFileIntoTable = idGen.newFunctionId(scope, "LoadCSVFileIntoTable");
			protoprov.AddFunction(provFxnLoadCSVFileIntoTable, "LoadCSVFileIntoTable", provGroups);
			protoprov.AddUsed(idGen.newRelationId("USD"), provFxnLoadCSVFileIntoTable, "file entry", provVarReadCSVFileColumnNamesOutput, provGroups);
			protoprov.AddUsed(idGen.newRelationId("USD"), provFxnLoadCSVFileIntoTable, "database", provVarCreateEmptyLoadDBOutput, provGroups);
			//protoprov.AddUsed(idGen.newRelationId("USD"), provFxnLoadCSVFileIntoTable, "check IsMatchCSVFileColumnNamesOutput", provVarIsMatchCSVFileColumnNamesOutput, provGroups);
			protoprov.AddWGB(idGen.newRelationId("WGB"), provVarLoadCSVFileIntoTableOutput, "output", provFxnLoadCSVFileIntoTable, provGroups);
			protoprov.AddWCB(idGen.newRelationId("WCB"), provFxnLoadCSVFileIntoTable, "controlled by", provCtlSys, provGroups);
			protoprov.AddWTB(idGen.newRelationId("WTB"), provFxnLoadCSVFileIntoTable, "passed control flow check", provFxnCheck_IsMatchCSVFileColumnNames, provGroups);			
			// END //	
						

			
			// 7.g. Control Flow: Decision

			// ANNOTATION //
			String provFxnCheck_LoadCSVFileIntoTable = idGen.newFunctionId(scope, "Check_LoadCSVFileIntoTable");
			protoprov.AddFunction(provFxnCheck_LoadCSVFileIntoTable, "Check_LoadCSVFileIntoTable", provGroups);
			protoprov.AddUsed(idGen.newRelationId("USD"), provFxnCheck_LoadCSVFileIntoTable, "control flow checkpoint", provVarLoadCSVFileIntoTableOutput, provGroups);
			// END//

			
			if (!LoadCSVFileIntoTableOutput) {
				String provFxnEndState = idGen.newFunctionId(scope, "EndState");
				protoprov.AddFunction(provFxnEndState, "EndState", provGroups);
				protoprov.AddWTB(idGen.newRelationId("WTB"), provFxnEndState, "failed control flow check", provFxnCheck_LoadCSVFileIntoTable, provGroups);			
				String provVarEndValue = idGen.newFunctionId(scope, "EndValue");
				protoprov.AddVariable(provVarEndValue, "false", provGroups);
				protoprov.AddWGB(idGen.newRelationId("WGB"), provVarEndValue, "end state value", provFxnEndState, provGroups);
				return protoprov;
			}

			if(ReadCSVFileColumnNamesOutput.TargetTable.equalsIgnoreCase("P2Detection")) {
				String dbEntry = LoadAppLogic.getDBEntry(CreateEmptyLoadDBOutput, ReadCSVFileColumnNamesOutput);
				provVarDbEntryP2Detection = idGen.newVariableId(scope, "DBEntry"+FileEntry.TargetTable, "provVarDbEntryP2Detection");
				protoprov.AddVariable(provVarDbEntryP2Detection, dbEntry, provGroups);
				protoprov.AddWGB(idGen.newRelationId("WGB"), provVarDbEntryP2Detection, "created by", provFxnLoadCSVFileIntoTable, provGroups);
			}
			else if(ReadCSVFileColumnNamesOutput.TargetTable.equalsIgnoreCase("P2ImageMeta")) {
				String dbEntry = LoadAppLogic.getDBEntry(CreateEmptyLoadDBOutput, ReadCSVFileColumnNamesOutput);
				provVarDbEntryP2ImageMeta = idGen.newVariableId(scope, "DBEntry"+FileEntry.TargetTable, "provVarDbEntryP2ImageMeta");
				protoprov.AddVariable(provVarDbEntryP2ImageMeta, dbEntry, provGroups);
				protoprov.AddWGB(idGen.newRelationId("WGB"), provVarDbEntryP2ImageMeta, "created by", provFxnLoadCSVFileIntoTable, provGroups);
			}
			
			// 7.h. UpdateComputedColumns
			boolean UpdateComputedColumnsOutput =
				LoadAppLogic.UpdateComputedColumns(CreateEmptyLoadDBOutput, ReadCSVFileColumnNamesOutput);

			// ANNOTATION //
			String provVarUpdateComputedColumnsOutput = idGen.newVariableId(scope, "boolean", "UpdateComputedColumnsOutput");
			protoprov.AddVariable(provVarUpdateComputedColumnsOutput, UpdateComputedColumnsOutput, provGroups);
			String provFxnUpdateComputedColumns = idGen.newFunctionId(scope, "UpdateComputedColumns");
			protoprov.AddFunction(provFxnUpdateComputedColumns, "UpdateComputedColumns", provGroups);
			protoprov.AddUsed(idGen.newRelationId("USD"), provFxnUpdateComputedColumns, "file entry", provVarReadCSVFileColumnNamesOutput, provGroups);
			protoprov.AddUsed(idGen.newRelationId("USD"), provFxnUpdateComputedColumns, "database", provVarCreateEmptyLoadDBOutput, provGroups);
			//protoprov.AddUsed(idGen.newRelationId("USD"), provFxnUpdateComputedColumns, "check LoadCSVFileIntoTableOutput", provVarLoadCSVFileIntoTableOutput, provGroups);
			protoprov.AddWGB(idGen.newRelationId("WGB"), provVarUpdateComputedColumnsOutput, "output", provFxnUpdateComputedColumns, provGroups);
			protoprov.AddWCB(idGen.newRelationId("WCB"), provFxnUpdateComputedColumns, "controlled by", provCtlSys, provGroups);
			protoprov.AddWTB(idGen.newRelationId("WTB"), provFxnUpdateComputedColumns, "passed control flow check", provFxnCheck_LoadCSVFileIntoTable, provGroups);			
			// END //	
						
			// 7.i. Control Flow: Decision

			// ANNOTATION //
			String provFxnCheck_UpdateComputedColumns = idGen.newFunctionId(scope, "Check_UpdateComputedColumns");
			protoprov.AddFunction(provFxnCheck_UpdateComputedColumns, "Check_UpdateComputedColumns", provGroups);
			protoprov.AddUsed(idGen.newRelationId("USD"), provFxnCheck_UpdateComputedColumns, "control flow checkpoint", provVarUpdateComputedColumnsOutput, provGroups);
			// END//

			
			if (!UpdateComputedColumnsOutput) {
				String provFxnEndState = idGen.newFunctionId(scope, "EndState");
				protoprov.AddFunction(provFxnEndState, "EndState", provGroups);
				protoprov.AddWTB(idGen.newRelationId("WTB"), provFxnEndState, "failed control flow check", provFxnCheck_UpdateComputedColumns, provGroups);			
				String provVarEndValue = idGen.newFunctionId(scope, "EndValue");
				protoprov.AddVariable(provVarEndValue, "false", provGroups);
				protoprov.AddWGB(idGen.newRelationId("WGB"), provVarEndValue, "end state value", provFxnEndState, provGroups);
				return protoprov;
			}

			// ///////////////////////////////////
			// //// PostLoad Validation //////
			// ///////////////////////////////////
			// 7.j. IsMatchTableRowCount
			boolean IsMatchTableRowCountOutput =
				LoadAppLogic.IsMatchTableRowCount(CreateEmptyLoadDBOutput, ReadCSVFileColumnNamesOutput);

			// ANNOTATION //
			String provVarIsMatchTableRowCountOutput = idGen.newVariableId(scope, "boolean", "IsMatchTableRowCountOutput");
			protoprov.AddVariable(provVarIsMatchTableRowCountOutput, IsMatchTableRowCountOutput, provGroups);
			String provFxnIsMatchTableRowCount = idGen.newFunctionId(scope, "IsMatchTableRowCount");
			protoprov.AddFunction(provFxnIsMatchTableRowCount, "IsMatchTableRowCount", provGroups);
			protoprov.AddUsed(idGen.newRelationId("USD"), provFxnIsMatchTableRowCount, "file entry", provVarReadCSVFileColumnNamesOutput, provGroups);
			protoprov.AddUsed(idGen.newRelationId("USD"), provFxnIsMatchTableRowCount, "database", provVarCreateEmptyLoadDBOutput, provGroups);
			//protoprov.AddUsed(idGen.newRelationId("USD"), provFxnIsMatchTableRowCount, "check UpdateComputedColumnsOutput", provVarUpdateComputedColumnsOutput, provGroups);
			protoprov.AddWGB(idGen.newRelationId("WGB"), provVarIsMatchTableRowCountOutput, "output", provFxnIsMatchTableRowCount, provGroups);
			protoprov.AddWCB(idGen.newRelationId("WCB"), provFxnIsMatchTableRowCount, "controlled by", provCtlSys, provGroups);
			protoprov.AddWTB(idGen.newRelationId("WTB"), provFxnIsMatchTableRowCount, "passed control flow check", provFxnCheck_UpdateComputedColumns, provGroups);			
			// END //	
			
			// 7.k. Control Flow: Decision

			// ANNOTATION //
			String provFxnCheck_IsMatchTableRowCount = idGen.newFunctionId(scope, "Check_IsMatchTableRowCount");
			protoprov.AddFunction(provFxnCheck_IsMatchTableRowCount, "Check_IsMatchTableRowCount", provGroups);
			protoprov.AddUsed(idGen.newRelationId("USD"), provFxnCheck_IsMatchTableRowCount, "control flow checkpoint", provVarIsMatchTableRowCountOutput, provGroups);
			// END//
			
			if (!IsMatchTableRowCountOutput) {
				String provFxnEndState = idGen.newFunctionId(scope, "EndState");
				protoprov.AddFunction(provFxnEndState, "EndState", provGroups);
				protoprov.AddWTB(idGen.newRelationId("WTB"), provFxnEndState, "failed control flow check", provFxnCheck_IsMatchTableRowCount, provGroups);			
				String provVarEndValue = idGen.newFunctionId(scope, "EndValue");
				protoprov.AddVariable(provVarEndValue, "false", provGroups);
				protoprov.AddWGB(idGen.newRelationId("WGB"), provVarEndValue, "end state value", provFxnEndState, provGroups);
				return protoprov;
			}

			// 7.l. IsMatchTableColumnRanges
			boolean IsMatchTableColumnRangesOutput =
				LoadAppLogic.IsMatchTableColumnRanges(CreateEmptyLoadDBOutput,
						ReadCSVFileColumnNamesOutput);
			

			// ANNOTATION //
			String provVarIsMatchTableColumnRangesOutput = idGen.newVariableId(scope, "boolean", "IsMatchTableColumnRangesOutput");
			protoprov.AddVariable(provVarIsMatchTableColumnRangesOutput, IsMatchTableColumnRangesOutput, provGroups);
			String provFxnIsMatchTableColumnRanges = idGen.newFunctionId(scope, "IsMatchTableColumnRanges");
			protoprov.AddFunction(provFxnIsMatchTableColumnRanges, "IsMatchTableColumnRanges", provGroups);
			protoprov.AddUsed(idGen.newRelationId("USD"), provFxnIsMatchTableColumnRanges, "file entry", provVarReadCSVFileColumnNamesOutput, provGroups);
			protoprov.AddUsed(idGen.newRelationId("USD"), provFxnIsMatchTableColumnRanges, "database", provVarCreateEmptyLoadDBOutput, provGroups);
			//protoprov.AddUsed(idGen.newRelationId("USD"), provFxnIsMatchTableColumnRanges, "check IsMatchTableRowCountOutput", provVarIsMatchTableRowCountOutput, provGroups);
			protoprov.AddWGB(idGen.newRelationId("WGB"), provVarIsMatchTableColumnRangesOutput, "output", provFxnIsMatchTableColumnRanges, provGroups);
			protoprov.AddWCB(idGen.newRelationId("WCB"), provFxnIsMatchTableColumnRanges, "controlled by", provCtlSys, provGroups);
			protoprov.AddWTB(idGen.newRelationId("WTB"), provFxnIsMatchTableColumnRanges, "passed control flow check", provFxnCheck_IsMatchTableRowCount, provGroups);			
			// END //	
						
			// 7.m. Control Flow: Decision
			
			// ANNOTATION //
			String provFxnCheck_IsMatchTableColumnRanges = idGen.newFunctionId(scope, "Check_IsMatchTableColumnRanges");
			protoprov.AddFunction(provFxnCheck_IsMatchTableColumnRanges, "Check_IsMatchTableColumnRanges", provGroups);
			protoprov.AddUsed(idGen.newRelationId("USD"), provFxnCheck_IsMatchTableColumnRanges, "control flow checkpoint", provVarIsMatchTableColumnRangesOutput, provGroups);
			// END//
			
			if (!IsMatchTableColumnRangesOutput) {
				String provFxnEndState = idGen.newFunctionId(scope, "EndState");
				protoprov.AddFunction(provFxnEndState, "EndState", provGroups);
				protoprov.AddWTB(idGen.newRelationId("WTB"), provFxnEndState, "failed control flow check", provFxnCheck_IsMatchTableColumnRanges, provGroups);			
				String provVarEndValue = idGen.newFunctionId(scope, "EndValue");
				protoprov.AddVariable(provVarEndValue, "false", provGroups);
				protoprov.AddWGB(idGen.newRelationId("WGB"), provVarEndValue, "end state value", provFxnEndState, provGroups);
				return protoprov;
			}

			lastCheck = provVarIsMatchTableColumnRangesOutput;
			counter++;
		}
		scope = "main";
		
		// 8. CompactDatabase
		LoadAppLogic.CompactDatabase(CreateEmptyLoadDBOutput);


		// ANNOTATION //
		String provVarCompactDatabaseOutput = idGen.newVariableId(scope, "void", "CompactDatabaseOutput");
		protoprov.AddVariable(provVarCompactDatabaseOutput, "void", provGroups);
		String provFxnCompactDatabase = idGen.newFunctionId(scope, "CompactDatabase");
		protoprov.AddFunction(provFxnCompactDatabase, "CompactDatabase", provGroups);
		protoprov.AddUsed(idGen.newRelationId("USD"), provFxnCompactDatabase, "database", provVarCreateEmptyLoadDBOutput, provGroups);
		protoprov.AddUsed(idGen.newRelationId("USD"), provFxnCompactDatabase, "IsMatchTableColumnRangesOutput check", lastCheck, provGroups);
		protoprov.AddWGB(idGen.newRelationId("WGB"), provVarCompactDatabaseOutput, "output", provFxnCompactDatabase, provGroups);
		protoprov.AddWCB(idGen.newRelationId("WCB"), provFxnCompactDatabase, "controlled by", provCtlSys, provGroups);

		
		String provFxnEndState = idGen.newFunctionId(scope, "EndState");
		protoprov.AddFunction(provFxnEndState, "EndState", provGroups);
		protoprov.AddWTB(idGen.newRelationId("WTB"), provFxnEndState, "failed control flow check", provFxnCompactDatabase, provGroups);			
		String provVarEndValue = idGen.newFunctionId(scope, "EndValue");
		protoprov.AddVariable(provVarEndValue, "true", provGroups);
		protoprov.AddWGB(idGen.newRelationId("WGB"), provVarEndValue, "end state value", provFxnEndState, provGroups);
		// END //	

		
//		OPMGen.printOPMGraph();
//		PMLGen.generatePMLProof(provVarCompactDatabaseOutput);
//		PMLGen.generatePMLProof(provVarDbEntryP2Detection);
//		PMLGen.generatePMLProof(provVarDbEntryP2ImageMeta);
//		RDFGen.genRDFStore();
//		Model retModel = GenRDFModel.genRDFStore(protoprov);
		
		return protoprov;
	}
}
